package com.scs.application.config;


import com.alibaba.druid.filter.config.ConfigFilter;
import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.modules.sys.properties.SpringYmlProperties;
import com.scs.application.modules.sys.properties.SystemProperties;
import com.scs.application.modules.sys.utils.UtilDatabase;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;

import javax.sql.DataSource;

/**
 * @Description：DRUID 配置
 */
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class DruidConfig {
    @Value("${spring.datasource.dynamic.datasource.master.username}")
    String username;

    @Value("${spring.profiles.active}")
    private String env;

    @Value("${spring.datasource.dynamic.datasource.master.url}")
    private String url;

    @Autowired
    private SystemProperties systemProperties;
    @Autowired
    private SpringYmlProperties springYmlProperties;

    @Autowired
    private DruidDataSourceCreator druidDataSourceCreator;

    public static final String ENV_SIT = "sit";
    public static final String ENV_PROD = "prod";

    /**
     * ===============================spring 监控  开始===============================
     */
    @Bean
    public DruidStatInterceptor druidStatInterceptor() {
        DruidStatInterceptor dsInterceptor = new DruidStatInterceptor();
        return dsInterceptor;
    }

    @Bean
    @Scope("prototype")
    public JdkRegexpMethodPointcut druidStatPointcut() {
        JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
        pointcut.setPatterns("com.scs.application.modules.*.mapper.*", "com.scs.application.modules.*.service.impl.*");
        return pointcut;
    }

    @Bean
    public DefaultPointcutAdvisor druidStatAdvisor(DruidStatInterceptor druidStatInterceptor, JdkRegexpMethodPointcut druidStatPointcut) {
        DefaultPointcutAdvisor defaultPointAdvisor = new DefaultPointcutAdvisor();
        defaultPointAdvisor.setPointcut(druidStatPointcut);
        defaultPointAdvisor.setAdvice(druidStatInterceptor);
        return defaultPointAdvisor;
    }
    /**  ===============================spring 监控 结束 =============================== */


    /**
     * =============================== SQL 监控 开始 ===============================
     */


    @Bean
    public Slf4jLogFilter logFilter() {

        Slf4jLogFilter logFilter = new Slf4jLogFilter();
        logFilter.setStatementExecutableSqlLogEnable(true);
        logFilter.setStatementLogEnabled(false);
        return logFilter;
    }

    @Bean
    public StatFilter statFilter() {

        StatFilter statFilter = new StatFilter();
        statFilter.setSlowSqlMillis(3000);
        statFilter.setLogSlowSql(true);
        statFilter.setMergeSql(true);
        return statFilter;
    }

    /**
     * sql防火墙过滤器配置
     *
     * @param wallConfig
     * @return
     */
    @Bean
    public WallFilter wallFilter(WallConfig wallConfig) {

        WallFilter wallFilter = new WallFilter();
        wallFilter.setConfig(wallConfig);
        //对被认为是攻击的SQL进行LOG.error输出
        wallFilter.setLogViolation(true);
        //对被认为是攻击的SQL抛出SQLException
        wallFilter.setThrowException(true);
        return wallFilter;
    }

    /**
     * sql防火墙配置
     *
     * @return
     */
    @Bean
    public WallConfig wallConfig() {

        WallConfig wallConfig = new WallConfig();
        wallConfig.setAlterTableAllow(false);
        wallConfig.setCreateTableAllow(false);
        wallConfig.setDeleteAllow(true);
        wallConfig.setMergeAllow(false);
        wallConfig.setDescribeAllow(false);
        wallConfig.setShowAllow(false);
        wallConfig.setMultiStatementAllow(true);
        wallConfig.setNoneBaseStatementAllow(true);
        return wallConfig;
    }
    /**  =============================== SQL 监控 结束 =============================== */


    /**
     * @return
     */
    @Bean
    public ConfigFilter configFilter() {
        ConfigFilter configFilter = new ConfigFilter();

        return configFilter;
    }


    /*
       将自定义的 Druid数据源添加到容器中，不再让 Spring Boot 自动创建
       绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效
       @ConfigurationProperties(prefix = "spring.datasource")：作用就是将 全局配置文件中
       前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
     */
//    @ConfigurationProperties(prefix = "spring.datasource")
//    @Bean
//    public DataSource druidDataSource() {
//
//        DruidDataSource druidDataSource = new DruidDataSource();
//
//        //添加默认账户密码对应关系
//        UtilDatabase.namePwdMap.put(springYmlProperties.getDatasource().getUsername(),springYmlProperties.getDatasource().getPassword());
//        //sit或生产环境，用户名密码进行特殊处理
//        if (StringUtils.equalsAny(env,ENV_SIT,ENV_PROD)){
//            //用户必须是spd
//            if (!"spd".equals(username)) throw new BusinessException("DruidConfig.druidDataSource.error，当前为生产环境，数据库连接请使用账户【spd】");
//            //创建数据库各类用户
//            UtilDatabase.initMysqlUsers(url.split(":")[2].replaceAll("//",""),systemProperties.getDbrootname(),systemProperties.getDbrootpwd());
//
//            Properties properties =druidDataSource.getConnectProperties();
//            properties.put("password",UtilDatabase.getPassword(username) );
//            //用户名及密码
//            druidDataSource.setConnectProperties(properties);
//        }
//        return druidDataSource;
//    }
    @Primary
    @Bean
    public DataSource dataSource() {

        String password = springYmlProperties.getDatasource().getPassword();
        //添加默认账户密码对应关系
        UtilDatabase.namePwdMap.put(springYmlProperties.getDatasource().getUsername(), springYmlProperties.getDatasource().getPassword());
        //sit或生产环境，用户名密码进行特殊处理
//        if (StringUtils.equalsAny(env, ENV_SIT, ENV_PROD)) {
//            //用户必须是spd
//            if (!"spd".equals(username))
//                throw new BusinessException("DruidConfig.druidDataSource.error，当前为生产环境，数据库连接请使用账户【spd】");
//            //创建数据库各类用户
//            UtilDatabase.initMysqlUsers(url.split(":")[2].replaceAll("//", ""), systemProperties.getDbrootname(), systemProperties.getDbrootpwd());
//
//            password = UtilDatabase.getPassword(username);
//            //用户名及密码
//        }
        DataSourceProperty dataSourceProperty = new DataSourceProperty();
        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();

        //用户名及密码
        dataSourceProperty.setPassword(password)
        .setUrl(url).setUsername(username);
        DataSource dataSource = druidDataSourceCreator.createDataSource(dataSourceProperty);
        dynamicRoutingDataSource.addDataSource("master", dataSource);
        dynamicRoutingDataSource.setPrimary("master");
        dynamicRoutingDataSource.setStrict(false);
        return dynamicRoutingDataSource;

    }
}
